/**
 * Error decoration and handling functionality for ArenaNext
 * Provides visual error indicators and error management in the editor
 */

/**
 * Setup error decorations with inline messages
 * @param {Object} monacoController - The Monaco controller instance
 * @returns {Object} Error decoration controller functions
 */
export function setupErrorDecorations(monacoController) {
  const monaco = monacoController.monacoController.monaco;
  const editor = monacoController.monacoController.monacoEditor;

  // 存储装饰器ID
  let errorDecorationIds = [];
  let warningDecorationIds = [];
  let infoDecorationIds = []; // 新增Info和Hint类型的装饰器ID数组
  let clearDecorationInterval = null;
  let isUpdating = false; // 防止递归调用

  // 当前光标所在行
  let currentCursorLine = -1;

  // 储存每行的错误信息，以便在光标移动时重新调整显示位置
  const lineErrorMap = new Map();

  /**
   * 获取标记优先级
   * @param {Number} severity - 标记严重性
   * @return {Number} 优先级值（值越小优先级越高）
   * @private
   */
  function getMarkerPriority(severity) {
    switch (severity) {
      case monaco.MarkerSeverity.Error:
        return 1; // 最高优先级
      case monaco.MarkerSeverity.Warning:
        return 2;
      case monaco.MarkerSeverity.Info:
        return 3;
      case monaco.MarkerSeverity.Hint:
        return 4;
      default:
        return 99;
    }
  }

  /**
   * 更新错误装饰器
   * @private
   */
  function updateErrorDecorations() {
    // 防止递归调用
    if (isUpdating || !editor || !editor.getModel()) return;

    try {
      isUpdating = true;

      const model = editor.getModel();
      if (!model) return; // 确保模型存在

      // 获取当前光标位置
      const selections = editor.getSelections();
      currentCursorLine =
        selections && selections.length > 0
          ? selections[0].startLineNumber
          : -1;

      // 获取当前模型的所有标记
      const markers = monaco.editor.getModelMarkers({ resource: model.uri });

      // 清空错误映射表
      lineErrorMap.clear();

      // 准备新的装饰
      const errorDecorations = [];
      const warningDecorations = [];
      const infoDecorations = [];

      // 行优先级跟踪 - 记录每行已处理的最高优先级
      const linePriorityMap = new Map();

      // 获取模型的总行数
      const lineCount = model.getLineCount();

      // 首先按优先级排序标记
      const sortedMarkers = [...markers].sort(
        (a, b) => getMarkerPriority(a.severity) - getMarkerPriority(b.severity)
      );

      // 如果有标记，处理它们
      if (sortedMarkers && sortedMarkers.length > 0) {
        // 按行分组最高优先级的标记
        const highestPriorityMarkersByLine = new Map();

        // 第一步：找出每行的最高优先级标记
        sortedMarkers.forEach((marker) => {
          // 安全检查：确保行号有效
          if (!marker || typeof marker.endLineNumber !== "number") return;
          if (marker.endLineNumber < 1 || marker.endLineNumber > lineCount)
            return;

          const lineNumber = marker.endLineNumber;
          const currentPriority = getMarkerPriority(marker.severity);

          // 如果该行尚未有标记或当前标记优先级更高，则更新
          if (
            !highestPriorityMarkersByLine.has(lineNumber) ||
            getMarkerPriority(
              highestPriorityMarkersByLine.get(lineNumber).severity
            ) > currentPriority
          ) {
            highestPriorityMarkersByLine.set(lineNumber, marker);
          }
        });

        // 第二步：只处理每行的最高优先级标记
        highestPriorityMarkersByLine.forEach((marker) => {
          // 额外的安全检查
          if (
            !marker ||
            typeof marker.endLineNumber !== "number" ||
            marker.endLineNumber < 1 ||
            marker.endLineNumber > lineCount
          ) {
            return;
          }

          // 获取行内容，用于确定是否有内容可以添加错误信息
          try {
            const lineContent = model.getLineContent(marker.endLineNumber);
            if (!lineContent) return; // 如果行为空，忽略该错误
          } catch (e) {
            console.warn(`获取行内容失败，行号: ${marker.endLineNumber}`, e);
            return; // 如果获取行内容失败，跳过此标记
          }

          const lineNumber = marker.endLineNumber;

          // 清空旧数据并存储错误信息到映射表
          if (!lineErrorMap.has(lineNumber)) {
            lineErrorMap.set(lineNumber, []);
          }
          // 只存储该行最高优先级的错误信息
          lineErrorMap.set(lineNumber, [
            {
              message: marker.message,
              severity: marker.severity,
            },
          ]);

          // 获取样式类名和颜色
          let className, glyphClassName, color, msgClassName, msgAboveClassName;

          switch (marker.severity) {
            case monaco.MarkerSeverity.Error:
              className = "error-line-highlight";
              glyphClassName = "error-glyph-margin";
              color = "rgba(255, 0, 0, 0.6)";
              msgClassName = "error-message-after-error";
              msgAboveClassName = "error-message-above-error";
              break;
            case monaco.MarkerSeverity.Warning:
              className = "warning-line-highlight";
              glyphClassName = "warning-glyph-margin";
              color = "rgba(241, 196, 15, 0.6)";
              msgClassName = "error-message-after-warning";
              msgAboveClassName = "error-message-above-warning";
              break;
            case monaco.MarkerSeverity.Info:
              className = "info-line-highlight";
              glyphClassName = "info-glyph-margin";
              color = "rgba(3, 169, 244, 0.6)";
              msgClassName = "error-message-after-info";
              msgAboveClassName = "error-message-above-info";
              break;
            case monaco.MarkerSeverity.Hint:
              className = "hint-line-highlight";
              glyphClassName = "hint-glyph-margin";
              color = "rgba(33, 150, 243, 0.6)";
              msgClassName = "error-message-after-hint";
              msgAboveClassName = "error-message-above-hint";
              break;
            default:
              return; // 跳过不支持的标记类型
          }

          try {
            // 创建行高亮装饰器
            const lineDecoration = {
              range: new monaco.Range(
                marker.startLineNumber,
                1,
                marker.endLineNumber,
                model.getLineMaxColumn(marker.endLineNumber)
              ),
              options: {
                isWholeLine: true,
                className: className,
                glyphMarginClassName: glyphClassName,
                overviewRuler: {
                  color: color,
                  position: monaco.editor.OverviewRulerLane.Right,
                },
              },
            };

            // 当前光标是否在该行
            const isCursorOnLine = marker.endLineNumber === currentCursorLine;

            // 创建错误消息装饰器
            let messageDecoration;

            if (isCursorOnLine) {
              // 光标在当前行 - 在上方显示错误信息
              // 确保上一行存在
              const aboveLine = Math.max(1, marker.endLineNumber - 1);
              if (aboveLine < 1 || aboveLine > lineCount) {
                // 如果上一行无效，则在当前行显示
                const currentLineMaxColumn = model.getLineMaxColumn(
                  marker.endLineNumber
                );
                messageDecoration = {
                  range: new monaco.Range(
                    marker.endLineNumber,
                    Math.max(1, currentLineMaxColumn - 1),
                    marker.endLineNumber,
                    currentLineMaxColumn
                  ),
                  options: {
                    isWholeLine: false,
                    after: {
                      content: ` // ${marker.message}`,
                      inlineClassName: msgClassName,
                    },
                    stickiness:
                      monaco.editor.TrackedRangeStickiness
                        .NeverGrowsWhenTypingAtEdges,
                  },
                };
              } else {
                // 上一行有效，显示在上方
                const aboveLineMaxColumn = model.getLineMaxColumn(aboveLine);
                messageDecoration = {
                  range: new monaco.Range(
                    aboveLine,
                    aboveLineMaxColumn,
                    aboveLine,
                    aboveLineMaxColumn
                  ),
                  options: {
                    isWholeLine: false,
                    after: {
                      content: `\n// ${marker.message}`,
                      inlineClassName: msgAboveClassName,
                    },
                    stickiness:
                      monaco.editor.TrackedRangeStickiness
                        .NeverGrowsWhenTypingAtEdges,
                  },
                };
              }
            } else {
              // 光标不在该行 - 在行尾显示错误信息
              const lineMaxColumn = model.getLineMaxColumn(
                marker.endLineNumber
              );
              messageDecoration = {
                range: new monaco.Range(
                  marker.endLineNumber,
                  Math.max(1, lineMaxColumn - 1), // 确保位于行尾，避免使用0或负数位置
                  marker.endLineNumber,
                  lineMaxColumn
                ),
                options: {
                  isWholeLine: false,
                  after: {
                    content: ` // ${marker.message}`,
                    inlineClassName: msgClassName,
                  },
                  stickiness:
                    monaco.editor.TrackedRangeStickiness
                      .NeverGrowsWhenTypingAtEdges,
                },
              };
            }

            // 添加到适当的装饰数组
            switch (marker.severity) {
              case monaco.MarkerSeverity.Error:
                errorDecorations.push(lineDecoration);
                errorDecorations.push(messageDecoration);
                break;
              case monaco.MarkerSeverity.Warning:
                warningDecorations.push(lineDecoration);
                warningDecorations.push(messageDecoration);
                break;
              case monaco.MarkerSeverity.Info:
              case monaco.MarkerSeverity.Hint:
                infoDecorations.push(lineDecoration);
                infoDecorations.push(messageDecoration);
                break;
            }
          } catch (e) {
            console.warn(`创建装饰器失败，行号: ${marker.endLineNumber}`, e);
          }
        });
      }

      // 一次性应用所有装饰，避免递归调用
      try {
        errorDecorationIds = editor.deltaDecorations(
          errorDecorationIds,
          errorDecorations
        );
        warningDecorationIds = editor.deltaDecorations(
          warningDecorationIds,
          warningDecorations
        );
        infoDecorationIds = editor.deltaDecorations(
          infoDecorationIds,
          infoDecorations
        );
      } catch (e) {
        console.error("应用装饰器时出错:", e);
        // 出错时清空所有装饰器
        clearDecorations();
      }
    } catch (error) {
      console.error("更新错误装饰器时出错:", error);
      // 出错时清空所有装饰器
      clearDecorations();
    } finally {
      isUpdating = false;
    }
  }

  /**
   * 清除所有错误装饰器
   * @private
   */
  function clearDecorations() {
    if (!editor) return;

    try {
      errorDecorationIds = editor.deltaDecorations(errorDecorationIds, []);
      warningDecorationIds = editor.deltaDecorations(warningDecorationIds, []);
      infoDecorationIds = editor.deltaDecorations(infoDecorationIds, []);
    } catch (error) {
      console.error("清除错误装饰器时出错:", error);
    }
  }

  // 初始化 - 延迟执行以避免初始化问题
  setTimeout(updateErrorDecorations, 100);

  // 安全地设置间隔检查 - 触发更新
  clearDecorationInterval = setInterval(() => {
    if (editor && editor.getModel()) {
      updateErrorDecorations();
    }
  }, 5000);

  // 事件监听器
  const markersListener = monaco.editor.onDidChangeMarkers(() => {
    updateErrorDecorations();
  });

  const modelListener = editor.onDidChangeModel(() => {
    // 当模型改变时，先清除旧装饰再更新
    clearDecorations();
    setTimeout(updateErrorDecorations, 50);
  });

  const cursorListener = editor.onDidChangeCursorPosition((e) => {
    // 光标位置变化时更新装饰
    if (currentCursorLine !== e.position.lineNumber) {
      currentCursorLine = e.position.lineNumber;
      setTimeout(updateErrorDecorations, 10);
    }
  });

  const contentListener = editor.onDidChangeModelContent(() => {
    // 内容变化后延迟更新，避免频繁更新
    setTimeout(updateErrorDecorations, 300);
  });

  // 添加CSS样式到文档中
  function addErrorStyles() {
    const styleId = "monaco-error-decoration-styles";
    if (!document.getElementById(styleId)) {
      const style = document.createElement("style");
      style.id = styleId;
      style.innerHTML = `
        .error-message-after-error {
          color: rgb(255, 100, 100) !important;
          margin-left: 4px;
          user-select: none;
          pointer-events: none;
        }
        .error-message-after-warning {
          color: rgb(250, 151, 58) !important;
          margin-left: 4px;
          user-select: none;
          pointer-events: none;
        }
        .error-message-after-info {
          color: rgb(0, 183, 228) !important;
          margin-left: 4px;
          user-select: none;
          pointer-events: none;
        }
        .error-message-after-hint {
          color: rgb(0, 183, 228) !important;
          margin-left: 4px;
          user-select: none;
          pointer-events: none;
        }
        .error-message-above-error {
          color: #f44336;
          background-color: rgba(244, 67, 54, 0.1);
          padding: 0 4px;
          user-select: none;
          pointer-events: none;
          display: block;
          text-align: right;
        }
        .error-message-above-warning {
          color: #ff9800;
          background-color: rgba(255, 152, 0, 0.1);
          padding: 0 4px;
          user-select: none;
          pointer-events: none;
          display: block;
          text-align: right;
        }
        .error-message-above-info {
          color: #03A9F4;
          background-color: rgba(3, 169, 244, 0.1);
          padding: 0 4px;
          user-select: none;
          pointer-events: none;
          display: block;
          text-align: right;
        }
        .error-message-above-hint {
          color: #2196F3;
          background-color: rgba(33, 150, 243, 0.1);
          padding: 0 4px;
          user-select: none;
          pointer-events: none;
          display: block;
          text-align: right;
        }
        .error-line-highlight {
          background-color: rgba(244, 67, 54, 0.1);
        }
        .warning-line-highlight {
          background-color: rgba(255, 152, 0, 0.1);
        }
        .info-line-highlight {
          background-color: rgba(3, 169, 244, 0.1);
        }
        .hint-line-highlight {
          background-color: rgba(33, 150, 243, 0.1);
        }
      `;
      document.head.appendChild(style);
    }
  }

  // 添加错误样式
  addErrorStyles();

  // 返回手动更新或清除错误装饰的函数
  return {
    update: updateErrorDecorations,
    clear: clearDecorations,
    dispose: () => {
      clearInterval(clearDecorationInterval);
      markersListener.dispose();
      modelListener.dispose();
      cursorListener.dispose();
      contentListener.dispose();
      clearDecorations();
    },
  };
}
